package com.spring.web.dispatch;

import com.spring.core.annotation.RequestParam;

import com.spring.core.context.AnnotationApplicationContext;
import com.spring.core.context.ApplicationContext;
import com.spring.util.StringUtil;


import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.Map;

/**
 * StringMVC dispatchServlet
 *
 * @author Zee
 * @date 2021年10月9日
 */
@WebServlet(name = "DispatchServlet")
public class DispatchServlet extends HttpServlet {

    /**
     * Spring容器
     */
    private ApplicationContext context;


    public DispatchServlet(ApplicationContext context) {
        this.context = context;
    }


    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            Object result = dispatch(request);
            if (null != result) {
                response.getWriter().write(String.valueOf(result));
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.getWriter().write("500" + Arrays.toString(e.getStackTrace()));
        }
    }


    /**
     * 委派执行对应的方法
     *
     * @param request request
     */
    private Object dispatch(HttpServletRequest request) throws Exception {
        String uri = request.getRequestURI();
        String contextPath = request.getContextPath();
        uri = uri.replaceAll(contextPath, "").replaceAll("/+", "/");
        if (!((AnnotationApplicationContext) context).getMapping().containsKey(uri)) {
            return "404";
        } else {
            Method method = ((AnnotationApplicationContext) context).getMapping().get(uri);
            Map<String, String[]> parameterMap = request.getParameterMap();
            String beanName = method.getDeclaringClass().getSimpleName();
            Object[] param = handleParam(method, parameterMap);
            Object obj = context.getBean(beanName);
            return method.invoke(obj, param);
        }
    }

    /**
     * 处理参数
     *
     * @param method       方法
     * @param parameterMap request传递参数map
     * @return object[]
     */
    private Object[] handleParam(Method method, Map<String, String[]> parameterMap) {
        Parameter[] parameters = method.getParameters();
        Object[] param = new Object[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            if (!parameters[i].isAnnotationPresent(RequestParam.class)) {
                continue;
            }
            RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
            param[i] = parameterMap.get(requestParam.value())[0];
        }
        return param;

    }


}
